class Parser

    prechigh
	    left TkLeftBracket TkRightBracket TkLeftBrace TkRightBrace TkLeftParentheses TkRightParentheses
	    nonassoc UMINUS TkNot
	    right TkPower TkExp
	    left TkAt TkDollar
	    left TkTimes TkDiv TkModulo 
	    left TkPeriod
	    left TkPlus TkMinus
	    nonassoc TkLessThan TkGreaterThan TkLessThanEqual TkGreaterThanEqual
	    nonassoc TkEqual TkNotEqual
	    left TkAnd
	    left TkOr
	    right TkAssign
	    nonassoc TkElse
	    nonassoc IF
    preclow

    token UMINUS IF TkNum TkNumID TkVec TkMat TkString TkId TkLeftBrace TkRightBrace TkLeftParentheses TkRightParentheses TkLeftBracket TkRightBracket TkPeriod TkPlus TkMinus TkTimes TkDiv TkModulo TkPower TkLessThan TkGreaterThan TkLessThanEqual TkGreaterThanEqual TkEqual TkNotEqual TkAt TkDollar TkNot TkAnd TkOr TkZeroes TkRange TkEye TkDefine TkOf TkType TkAs TkBegin TkEnd TkVars TkIf TkThen TkElse TkWhile TkDo TkForeach TkIn TkRead TkWrite TkReturn TkAssign TkComma TkSemiColon TkColon TkBoolean TkExp

rule

    target:
        PROGRAM    { }
;
    PROGRAM:
        DECFUN INSTR    { }
      | INSTR           { }
;
    DECFUN:
        DEFFUN DECFUN    { }
      | DEFFUN           { }
;
    DEFFUN:
        FIRMFUN INSTRFUN    { }
;
    FIRMFUN:
        TkDefine TkId TkLeftParentheses LISTVAR TkRightParentheses TkOf TkType TYPE TkAs    { }
      | TkDefine TkId TkLeftParentheses TkRightParentheses TkOf TkType TYPE TkAs            { }
;
    LISTVAR:
        TkId TkColon TYPE TkComma LISTVAR    { }
      | TkId TkColon TYPE                    { }
;
    TYPE:
        TkNumID    { }
      | TkVec      { }
      | TkMat      { }
;
    INSTRFUN:
        TkId TkAssign EXPR                               { }
      | TkRead ASSIGN                                    { }
      | TkWrite LEXPR                                    { }
      | TkWrite TkString                                 { }
      | TkWhile EXPRBOOL TkDo INSTRFUN                   { }
      | TkForeach TkId TkIn EXPR TkDo INSTRFUN           { }
      | TkBegin DECVAR LINSTRFUN TkEnd                   { }
      | TkBegin LINSTRFUN TkEnd                          { }
      | TkIf EXPRBOOL TkThen INSTRFUN TkElse INSTRFUN    { }
      | TkIf EXPRBOOL TkThen INSTRFUN =IF                { }
      | TkReturn EXPR                                    { }
;
    LINSTRFUN:
        INSTRFUN TkSemiColon LINSTRFUN    { }
      | INSTRFUN                          { }
;
    INSTR:
        ASSIGN TkAssign EXPR                       { }
      | TkRead ASSIGN                              { }
      | TkWrite LEXPR                              { }
      | TkWrite TkString                           { }
      | TkWhile EXPRBOOL TkDo INSTR                { }
      | TkForeach TkId TkIn EXPR TkDo INSTR        { }
      | TkBegin DECVAR LINSTR TkEnd                { }
      | TkBegin LINSTR TkEnd                       { }
      | TkIf EXPRBOOL TkThen INSTR TkElse INSTR    { }
      | TkIf EXPRBOOL TkThen INSTR =IF             { }
;
    DECVAR:
        TkVars LISTDEC    { }
;
    LISTDEC:
        VARS TkColon TYPE TkSemiColon LISTDEC    { }
      | VARS TkColon TYPE                        { }
;
    VARS:
        TkId TkComma VARS    { }
      | TkId                 { }
;
    LINSTR:
        INSTR TkSemiColon LINSTR    { }
      | INSTR                       { }
;
    LEXPR:
        EXPR TkComma LEXPR    { }
      | EXPR                  { }
;
    ASSIGN:
        TkId                                                                                                 { }
      | TkId TkLeftBracket EXPR TkComma EXPR TkRightBracket                                                  { }
      | TkId TkLeftBracket EMPTYEXPR TkColon EMPTYEXPR TkRightBracket                                        { }
      | TkId TkLeftBracket EMPTYEXPR TkColon EMPTYEXPR TkComma EMPTYEXPR TkColon EMPTYEXPR TkRightBracket    { }
;
    EXPRBOOL:
        TkBoolean                       { }
      | EXPRBOOL TkAnd EXPRBOOL         { }
      | EXPRBOOL TkOr EXPRBOOL          { }
      | EXPRBOOL TkEqual EXPRBOOL       { }
      | TkNot EXPRBOOL                  { }
      | EXPR TkLessThan EXPR            { }
      | EXPR TkGreaterThan EXPR         { }
      | EXPR TkLessThanEqual EXPR       { }
      | EXPR TkGreaterThanEqual EXPR    { }
      | EXPR TkEqual EXPR               { }
      | EXPR TkNotEqual EXPR            { }
;
    EMPTYEXPR:
        EXPR    { }
      |         { }
;
    EXPR:
        TkNum                                                              { }
      | TkMinus EXPR =UMINUS                                               { }
      | EXPR TkPlus EXPR                                                   { }
      | EXPR TkMinus EXPR                                                  { }
      | EXPR TkTimes EXPR                                                  { }
      | EXPR TkDiv EXPR                                                    { }
      | EXPR TkModulo EXPR                                                 { }
      | EXPR TkPower EXPR                                                  { }
      | TkAt EXPR                                                          { }
      | TkExp EXPR                                                         { }
      | TkDollar EXPR                                                      { }
      | TkId TkLeftParentheses LEXPR TkRightParentheses                    { }
      | TkZeroes TkLeftParentheses EXPR TkRightParentheses                 { }
      | TkZeroes TkLeftParentheses EXPR TkComma EXPR TkRightParentheses    { }
      | TkRange TkLeftParentheses EXPR TkRightParentheses                  { }
      | TkEye TkLeftParentheses EXPR TkRightParentheses                    { }
      | TkLeftBrace LVM TkRightBrace                                       { }
      | ASSIGN                                                             { }
;
    LVM:
        LEXPR                      { }  
      | LEXPR TkSemiColon LEXPR    { }
;

---- header ----

# Parser.rb: generated by racc
require 'Lexer'

---- inner ----

    attr_reader :lexer, :tok
    def initialize(lexer)
        @lexer = lexer
        @tok = nil
    end

    def parse
        do_parse
    end

    def next_token
        @tok = @lexer.yylex()
        if @tok == nil
            return [false,false]
        end
        return [:"#{@tok.class}", @tok.value]
    end

    def on_error(err_token_id, err_val, val_stack)
        excp = ParserError.new(@tok)
        raise excp
    end

---- footer ----

class ParserError < Exception

    attr_reader :token

    def initialize(tok)
        @token = tok
    end

    def to_s
        if (@token == nil)
          puts "Error de sintaxis al final del archivo."
        else
          puts "Error de sintaxis: \"#{@token.value}\" invalido en la linea #{@token.line}, columna #{@token.col}"
        end
    end

end
